package com.monitor.listenter;

import com.monitor.common.Md5Util;
import com.monitor.common.MonitorConstants;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName TaskDataListenter
 * @Package com.monitor.listenter
 * @Description 后台管理定时任务分片监听器
 * @Author zhixingbai
 * @Create 2018/10/2914:35
 */
@Service
public class TaskDataListenter {

    private  final Logger logger=LoggerFactory.getLogger(this.getClass());

    private ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1);

    @Resource
    protected StringRedisTemplate stringRedisTemplate;


    @PostConstruct
    public void startDataSplit() {
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                taskDataSplit();
            }
        },1,16,TimeUnit.SECONDS);
    }
    public void taskDataSplit() {
        logger.info("定时任务监听数据分片开始运行");
        try {
            //1.获取注册的定时任务实例
            Set<String> regNodes = stringRedisTemplate.opsForSet().members(MonitorConstants.MACHINENAME_REG);
            if(CollectionUtils.isNotEmpty(regNodes)){
                logger.info("定时任务监听数据分片注册实例：{}" ,Arrays.toString(regNodes.toArray()));
            }else {
                logger.info("定时任务监听数据分片注册实例：0");
                return;
            }
            String liveNode = "";
            List<String> liveNodes = new ArrayList<String>();
            //2.获取存活的实例
            for (String reg : regNodes) {
                String nodeLive = stringRedisTemplate.opsForValue().get(reg+MonitorConstants.MACHINENAME_SUFFIX);
                if(StringUtils.isNotEmpty(nodeLive)){
                    liveNodes.add(nodeLive);
                    liveNode += reg;
                }
            }
            logger.info("定时任务监听数据分片存活的实例：{}" ,liveNode);
            //3.判断是否需要重新分配分片数据
            if(StringUtils.isNotEmpty(liveNode)){
                String md5LiveNode =  stringRedisTemplate.opsForValue().get("TASK_NODE_MD5");
                logger.info("缓存中的节点对应的md5信息：{}",md5LiveNode);
                String md5Node = Md5Util.encodeMessage(liveNode);
                logger.info("存活的节点对应的md5信息：{}",md5Node);
                if(!md5Node.equals(md5LiveNode)){
                    ////存活120秒强制计算
                    stringRedisTemplate.opsForValue().set("TASK_NODE_MD5", md5Node,120,TimeUnit.SECONDS);
                    splitData(liveNodes);
                }
            }

        } catch (Exception e) {
            logger.error("定时任务监听数据分片运行异常", e);
        }
        logger.info("定时任务监听数据分片结束运行");
    }

    private void splitData(List<String> liveNodes) {
        //1.分片数据
        Integer[] numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        Map<String, String> split = new HashMap<String, String>();
        for (int i = 0; i < numbers.length; i++) {
            int index = numbers[i] % liveNodes.size();
            if (split.containsKey(liveNodes.get(index))) {
                String s = split.get(liveNodes.get(index));
                split.put(liveNodes.get(index), s + "," + numbers[i]);
            } else {
                split.put(liveNodes.get(index), String.valueOf(numbers[i]));
            }
        }
        //2.输出数据分片
        for (Map.Entry<String, String> entry : split.entrySet()) {
            logger.info("定时任务监听数据分片的key={},value={}",entry.getKey(),entry.getValue());
            //存活150秒
            stringRedisTemplate.opsForValue().set(entry.getKey(),entry.getValue(),150,TimeUnit.SECONDS);
        }
    }


}
